package org.pylates;

import java.io.Reader;
import java.util.HashMap;
import java.util.Map;

import org.antlr.stringtemplate.StringTemplate;
import org.antlr.stringtemplate.StringTemplateErrorListener;
import org.antlr.stringtemplate.StringTemplateGroup;

public class PyTemplateGroup extends StringTemplateGroup {

	private PythonFacade python;

	public void setPython(PythonFacade python) {
		this.python = python;
	}

	public PythonFacade getPython() {
		return python;
	}

	/**
	 * Create a group manager for some templates, all of which are loaded as
	 * resources via the classloader.
	 */
	public PyTemplateGroup(String name) {
		this(name, (String) null);
	}

	/**
	 * Create a group manager for some templates, all of which are at or below
	 * the indicated directory.
	 */
	public PyTemplateGroup(String name, String rootDir) {
		super(name, rootDir, null);
	}

	/**
	 * Create a group from the template group defined by a input stream. The
	 * name is required.
	 */
	public PyTemplateGroup(String name, Reader reader) {
		this(name, reader, DEFAULT_ERROR_LISTENER, (StringTemplateGroup) null);
	}

	/**
	 * Specify errors listener
	 * 
	 * @param name
	 * @param reader
	 * @param errors
	 */
	public PyTemplateGroup(String name, Reader reader, StringTemplateErrorListener errors) {
		this(name, reader, errors, (StringTemplateGroup) null);
	}

	/**
	 * Create a group from the input stream. Ignore any lexers, since we use
	 * python as external interpreter
	 */
	public PyTemplateGroup(String name, Reader reader, StringTemplateErrorListener errors,
	        StringTemplateGroup superGroup) {
		super(reader, null, errors, superGroup);
		this.name = name;
		this.init();
	}

	private void init() {
		if (python == null) {
			this.python = new PythonFacade();
		}
	}

	/**
	 * Cache for templates
	 */
	private Map<String, PyTemplate> pyTemplates = new HashMap<String, PyTemplate>();

	/**
	 * lookup for template by name
	 * 
	 * @param enclosingInstance
	 * @param name
	 * @return
	 * @throws IllegalArgumentException
	 */
	/*
	 * public synchronized StringTemplate lookupTemplate( PyTemplate
	 * enclosingInstance, String name) throws IllegalArgumentException { // try
	 * to get python instance else try load within parent return null; }
	 */

	@Override
	public synchronized StringTemplate lookupTemplate(StringTemplate enclosingInstance, String name)
	        throws IllegalArgumentException {
		StringTemplate st = null;
		// look in cache
		if (!pyTemplates.containsKey(name)) {
			// construct new
			st = getPython().buildPyTemplate(name);
			st.setGroup(this);
		} else {
			// return from cache
			st = pyTemplates.get(name);
		}
		if (st != null)
			return st;
		// else
		return super.lookupTemplate(enclosingInstance, name);
	}

	@Override
	protected void parseGroup(Reader reader) {
		try {
			init();
			python.compile(reader);
		} catch (Exception e) {
			String name = "<unknown>";
			if (getName() != null) {
				name = getName();
			}
			error("problem parsing group " + name + ": " + e, e);
		}
	}

	@Override
	protected void verifyInterfaceImplementations() {
		// TODO Auto-generated method stub
		super.verifyInterfaceImplementations();
	}

	@Override
	public StringTemplate createStringTemplate() {
		PyTemplate pt = new PyTemplate();
		return pt;
	}

}
